#include "ccontrol.h"

CControl::CControl(QObject *parent) :
    QObject(parent)
{
    m_MatrixWidth = 0;

    m_MatrixHeight = 0;

    m_score = 0;

    m_LeastDestoyCnt = 3;

    //m_LastSpace.clear();

    m_MovePath.clear();

    m_BallList.clear();

    m_CheckedBallCoordinate = QPoint(0, 0);

    m_NextBallCnt = 3;

    m_BallTypeCnt = qMin(m_NextBallCnt + 2, (int)eColorTypeCnt);

    //reset(startBallCnt, m_NextBallCnt, m_BallTypeCnt, width, height);

}

///
/// \brief CControl::ClearPreState
/// 清理之前的状态
///
void CControl::ClearPreState()
{
    // 析构之前的内容
    //m_LastSpace.clear();
    for (int i = 0; i < m_MatrixWidth ; i++)
    {
        for (int j = 0; j < m_MatrixHeight; j++)
        {
            CChecked* pChecked = m_CheckedMatrix[CoordinateToIdx(i, j)];
            if (pChecked)
            {
                delete pChecked;
            }
        }
    }

    for (int i = 0 ; i < m_BallList.count(); i++)
    {
        CBall* pball = m_BallList[i];
        delete pball;
    }
    m_BallList.clear();

    // 分数清零
    m_score = 0;
}


///
/// \brief reset
/// 重新开始游戏
///
/// \param startBallCnt
/// 开始时 小球的数量
///
/// \param nextBallCnt
/// 每次更新的时候 的小球的数量
///
/// \param width
/// 棋盘的 宽度
///
/// \param height
/// 棋盘的 高度
///
void CControl::reset(int startBallCnt, int nextBallCnt, int ballTypeCnt, int leastDestoyCnt, int width, int height)
{
    // 清理之前的状态
    ClearPreState();

    // 设置当前的状态
    m_NextBallCnt = nextBallCnt;

    m_MatrixWidth = width;

    m_MatrixHeight = height;

    m_BallTypeCnt = qMin(ballTypeCnt, (int)(eColorTypeCnt));

    m_LeastDestoyCnt = leastDestoyCnt;

    // 建立棋盘矩阵
    m_CheckedMatrix = new CChecked*[m_MatrixWidth * m_MatrixHeight];

    for (int i = 0; i < m_MatrixWidth ; i++)
    {
        for (int j = 0; j < m_MatrixHeight; j++)
        {
            CChecked *pChecked = new CChecked(this);
            m_CheckedMatrix[CoordinateToIdx(i, j)] = pChecked;
            pChecked->addBall(NULL);

            //QPoint point(i, j);
            //m_LastSpace.append(point);
        }
    }

    // 生成第一次的小球
    //QList<CBall*> newBallList;
    CreaterBall(startBallCnt, m_NewBallList);

    NextStep();

    //OutputMatrix();

}
///
/// \brief NextStep
/// 进行下个步骤
/// 1.如果有可以消除的小球 则计算分数 消除小球 刷新棋盘 并等待一段时间 显示
/// 2.将之前生成的小球摆放到棋盘上 刷新棋盘 等待一段时间
/// 3.计算是否有可以消除的小球，消除小球，刷新棋盘，并等待一段时间
/// 4.生成新的小球 抛出新的小球生成信号 信号参数包含小球的指针
///
/// \return
/// true 还有剩余的位子可以添加小球 游戏继续
/// false 没有剩余的位子可以添加小球了 游戏结束
///
bool CControl::NextStep()
{
    // 获取空闲的棋盘位置
    QList < QPoint > spaceChecked;
    spaceChecked = GetSpaceChecked();
    if (spaceChecked.count() <= m_NewBallList.count())
    {
        return false;
    }

    // 1.如果有可以消除的小球 则计算分数 消除小球 刷新棋盘 并等待一段时间 显示
    QList <QPoint> destroyBall;
    destroyBall = NumberOfStatisticalDestroyBalls();

    if (destroyBall.count() > 0)
    {
        dbglobal::MyMSleep(500);
        //计算 分数
        m_score += CalScoreAndDisBall(destroyBall);
        emit updateScore(m_score);
        dbglobal::MyMSleep(500);

        spaceChecked = GetSpaceChecked();
        if (spaceChecked.count() > 0)
        {
            // 如果此盘有消除的 且棋盘中还有空余的格子
            // 此盘轮空
            return true;
        }
    }

    // 2.将之前生成的小球摆放到棋盘上 刷新棋盘 等待一段时间
    for (int i = 0, irand; i < m_NewBallList.count(); i++)
    {
        spaceChecked = GetSpaceChecked();
        struct timeval tv;
        gettimeofday(&tv, NULL);
        srand(tv.tv_usec);
        irand = rand() % spaceChecked.count();
        QThread::usleep(irand);

        QPoint coordinate = spaceChecked.at(irand);
        int x = coordinate.x(), y = coordinate.y();
        //m_LastSpace.removeAt(irand);

        gettimeofday(&tv, NULL);
        srand(tv.tv_usec);
        irand = rand() % m_BallTypeCnt;
        QThread::usleep(irand);

        CBall *pBall = m_NewBallList.at(i);
        CChecked *pChecked = m_CheckedMatrix[CoordinateToIdx(x, y)];
        pChecked->addBall(pBall);
        m_BallList.append(pBall);
    }

    if (m_NewBallList.count() > 0)
    {
        dbglobal::MyMSleep(500);
    }

    // 3.计算是否有可以消除的小球，消除小球，刷新棋盘，并等待一段时间
    destroyBall.clear();
    destroyBall = NumberOfStatisticalDestroyBalls();
    if (destroyBall.count() > 0)
    {
        //计算 分数
        m_score += CalScoreAndDisBall(destroyBall);
        emit updateScore(m_score);
        dbglobal::MyMSleep(500);
    }

    // 4.生成新的小球 抛出新的小球生成信号 信号参数包含小球的指针
    if ( CreaterBall(m_NextBallCnt, m_NewBallList) == true)
    {

        QList < CBall > newballlist;
        for (int i = 0 ; i < m_NewBallList.count(); i++)
        {
            CBall *pBall = m_NewBallList[i];
            CBall ball(*pBall);
            newballlist.append(ball);
        }/**/
        emit CreatedNewBall(newballlist);
    }

    return true;
}


bool CControl::CreaterBall(int nextBallCnt, QList<CBall*> &newBallList)
{
    newBallList.clear();
    for (int i = 0, irand; i < nextBallCnt; i++)
    {
        struct timeval tv;
        gettimeofday(&tv, NULL);
        srand(tv.tv_usec);
        irand = rand() % m_BallTypeCnt;
        QThread::usleep(irand);

        //irand = 1;
        CBall *pBall = new CBall(irand, this);
        newBallList.append(pBall);
    }

    return true;
}

// 获取小球的路径
bool CControl::GetPath(QPoint sourPoint, QPoint destPoint)
{
    bool ret = false;

    // 生成矩阵
    int **matrix; /*= new int[m_MatrixWidth * m_MatrixHeight];*/

    matrix = new int* [m_MatrixWidth];
    for (int i = 0; i < m_MatrixWidth; i++)
    {
        matrix[i] = new int[m_MatrixHeight];
    }

    for (int i = 0; i < m_MatrixWidth; i++)
    {
        for (int j = 0; j < m_MatrixHeight; j++)
        {
            if (m_CheckedMatrix[CoordinateToIdx(i, j)]->hasBall() == true)
            {
                //matrix[CoordinateToIdx(i, j)] = CAlgorithm::eMatrixStateObstacle;
                matrix[i][j] = CAlgorithm::eMatrixStateObstacle;
            }
            else
            {
                //matrix[CoordinateToIdx(i, j)] = CAlgorithm::eMatrixStateNone;
                matrix[i][j] = CAlgorithm::eMatrixStateNone;
            }
        }
    }

    // 清理之前的路径
    m_MovePath.clear();

    // 获取路径
    //ret = m_CAlgorithm.GetPathDFS(sourPoint, destPoint,
    //                     matrix, m_MatrixWidth, m_MatrixHeight,
    //                     m_MovePath);
    ret = m_CAlgorithm.GetPathBFS(sourPoint, destPoint,
                         matrix, m_MatrixWidth, m_MatrixHeight,
                         m_MovePath);

    return ret;
}



// 移动小球
bool CControl::MoveBall(QPoint sourPoint, QPoint destPoint)
{
    // GetPath 会修改  m_MovePath
    if (GetPath(sourPoint, destPoint) == true)
    {
        int idxSource = CoordinateToIdx(sourPoint);
        int idxDest = CoordinateToIdx(destPoint);
        m_CheckedMatrix[idxSource]->swapBall(m_CheckedMatrix[idxDest]->GetBall());

        return true;
    }

    return false;
}

///
/// \brief CControl::CalScoreAndDisBall
/// 计算得分 并且消除小球
///
/// \return
///
int CControl::CalScoreAndDisBall(QList <QPoint> destroyBall)
{
    if (destroyBall.count() == 0)
    {
        return 0;
    }

    // 计算分数
    int score = 0;
    if (destroyBall.count() > 0)
    {
        score = m_LeastDestoyCnt;
    }
    for (int i = 0 ; i < destroyBall.count() - m_LeastDestoyCnt; i++)
    {
        score += ( i + 2);
    }
    //qDebug() << "score : " << score;

    // 归还空间
    RestoreSpace(destroyBall);

    //OutputMatrix();

    if (destroyBall.count() > 0)
    {
        emit updateScore(score);
    }

    return score;
}


///
/// \brief CControl::NumberOfStatisticalDestroyBalls
/// 统计可以消除的小球
///
/// \return
/// 可以消除的小球的列表
/// 可以会重复 因为可能会多项消除
///
QList <QPoint> CControl::NumberOfStatisticalDestroyBalls()
{
    QList <QPoint> destroyPoint;

    // 计算横向
    //qDebug() << "横向";
    /*
    for (int i = 0 ; i < m_MatrixWidth; i++)
    {
        int curBallType = eColorTypeNone;
        QList <QPoint> curDestroyPoint;
        curDestroyPoint.clear();
        for (int j = 0; j < m_MatrixHeight; j ++)
        {
            CChecked *pChecker = m_CheckedMatrix[CoordinateToIdx(i, j)];
            if (pChecker->hasBall() == false)
            {// 如果这个点 没有小球 则清空
                if (curDestroyPoint.count() >= m_LeastDestoyCnt)
                {
                    // 判断之前的数量够不够消除的数量
                    // 如果之前的计数已经够消除了 则记录下消除的位置
                    destroyPoint.append(curDestroyPoint);
                    //qDebug() << curDestroyPoint;
                }

                curDestroyPoint.clear();
                curBallType = eColorTypeNone;
            }
            else
            {
                pBall = pChecker->GetBall();
                //destroyPoint.append(QPoint(i, j));
                if (curBallType == eColorTypeNone)
                {
                    // 如果这个是新的小球 则初始化当前小球类型和计数
                    // 将当前位置 添加到 代销处的位置上
                    curBallType = pBall->GetBallType();
                    curDestroyPoint.clear();
                }
                else
                {
                    if (curBallType != pBall->GetBallType())
                    {// 如果和上一个颜色不同
                        if (curDestroyPoint.count() >= m_LeastDestoyCnt)
                        {
                            // 判断之前的数量够不够消除的数量
                            // 如果之前的计数已经够消除了 则记录下消除的位置
                            destroyPoint.append(curDestroyPoint);
                            //qDebug() << curDestroyPoint;
                        }

                        curBallType = pBall->GetBallType();
                        curDestroyPoint.clear();
                    }
                }

                curDestroyPoint.append(QPoint(i, j));
            }
        }

        if (curDestroyPoint.count() >= m_LeastDestoyCnt)
        {
            // 判断之前的数量够不够消除的数量
            // 如果之前的计数已经够消除了 则记录下消除的位置
            destroyPoint.append(curDestroyPoint);
            //qDebug() << curDestroyPoint;
        }

    }
    */
    // 计算纵向
    //qDebug() << "纵向";
    /*
    for (int j = 0; j < m_MatrixHeight; j ++)
    {
        int curBallType = eColorTypeNone;
        QList <QPoint> curDestroyPoint;
        curDestroyPoint.clear();
        for (int i = 0 ; i < m_MatrixWidth; i++)
        {
            CChecked *pChecker = m_CheckedMatrix[CoordinateToIdx(i, j)];
            if (pChecker->hasBall() == false)
            {// 如果这个点 没有小球 则清空
                if (curDestroyPoint.count() >= m_LeastDestoyCnt)
                {
                    // 判断之前的数量够不够消除的数量
                    // 如果之前的计数已经够消除了 则记录下消除的位置
                    destroyPoint.append(curDestroyPoint);
                    //qDebug() << curDestroyPoint;
                }

                curDestroyPoint.clear();
                curBallType = eColorTypeNone;
            }
            else
            {
                pBall = pChecker->GetBall();
                //destroyPoint.append(QPoint(i, j));
                if (curBallType == eColorTypeNone)
                {
                    // 如果这个是新的小球 则初始化当前小球类型和计数
                    // 将当前位置 添加到 代销处的位置上
                    curBallType = pBall->GetBallType();
                    curDestroyPoint.clear();
                }
                else
                {
                    if (curBallType != pBall->GetBallType())
                    {// 如果和上一个颜色不同
                        if (curDestroyPoint.count() >= m_LeastDestoyCnt)
                        {
                            // 判断之前的数量够不够消除的数量
                            // 如果之前的计数已经够消除了 则记录下消除的位置
                            destroyPoint.append(curDestroyPoint);
                            //qDebug() << curDestroyPoint;
                        }

                        curBallType = pBall->GetBallType();
                        curDestroyPoint.clear();
                    }
                }

                curDestroyPoint.append(QPoint(i, j));
            }
        }

        if (curDestroyPoint.count() >= m_LeastDestoyCnt)
        {
            // 判断之前的数量够不够消除的数量
            // 如果之前的计数已经够消除了 则记录下消除的位置
            destroyPoint.append(curDestroyPoint);
            //qDebug() << curDestroyPoint;
        }
    }
    */

    // 计算横向
    for (int i = 0 ; i < m_MatrixWidth; i++)
    {
        int curBallType = eColorTypeNone;
        QList <QPoint> curDestroyPoint;
        curDestroyPoint.clear();
        for (int j = 0; j < m_MatrixHeight; j ++)
        {
            //CChecked *pChecker = m_CheckedMatrix[CoordinateToIdx(i, j)];
            CalALineDestoryBallCnt(i, j, curBallType, curDestroyPoint, destroyPoint);
        }

        if (curDestroyPoint.count() >= m_LeastDestoyCnt)
        {
            // 判断之前的数量够不够消除的数量
            // 如果之前的计数已经够消除了 则记录下消除的位置
            destroyPoint.append(curDestroyPoint);
            //qDebug() << curDestroyPoint;
        }
    }

    // 计算纵向
    for (int j = 0; j < m_MatrixHeight; j ++)
    {
        int curBallType = eColorTypeNone;
        QList <QPoint> curDestroyPoint;
        curDestroyPoint.clear();
        for (int i = 0 ; i < m_MatrixWidth; i++)
        {
            //CChecked *pChecker = m_CheckedMatrix[CoordinateToIdx(i, j)];
            CalALineDestoryBallCnt(i, j, curBallType, curDestroyPoint, destroyPoint);
        }

        if (curDestroyPoint.count() >= m_LeastDestoyCnt)
        {
            // 判断之前的数量够不够消除的数量
            // 如果之前的计数已经够消除了 则记录下消除的位置
            destroyPoint.append(curDestroyPoint);
            //qDebug() << curDestroyPoint;
        }
    }

    // 东南向遍历上半矩阵
    for (int i = 0 ; i < m_MatrixWidth; i++)
    {
        int curBallType = eColorTypeNone;
        QList <QPoint> curDestroyPoint;
        curDestroyPoint.clear();
        for (int j =0; j < m_MatrixWidth - i; j ++)
        {
            //CChecked *pChecked = m_CheckedMatrix[CoordinateToIdx(i + j, j)];
            CalALineDestoryBallCnt(i + j, j, curBallType, curDestroyPoint, destroyPoint);

        }
        if (curDestroyPoint.count() >= m_LeastDestoyCnt)
        {
            destroyPoint.append(curDestroyPoint);
        }
    }

    // 东南向遍历下半矩阵
    for (int i = 0; i < m_MatrixWidth; i ++)
    {
        int curBallType = eColorTypeNone;
        QList <QPoint> curDestroyPoint;
        curDestroyPoint.clear();
        for (int j = i ; j < m_MatrixWidth - 1; j ++)
        {
            //CChecked *pChecked = m_CheckedMatrix[CoordinateToIdx(j - i, j + 1)];
            CalALineDestoryBallCnt(j - i, j + 1, curBallType, curDestroyPoint, destroyPoint);
        }

        if (curDestroyPoint.count() >= m_LeastDestoyCnt)
        {
            destroyPoint.append(curDestroyPoint);
        }
    }

    // 西南向遍历上半矩阵
    for (int i = 0 ; i < m_MatrixWidth; i ++)
    {
        int curBallType = eColorTypeNone;
        QList <QPoint> curDestroyPoint;
        curDestroyPoint.clear();
        for (int j = 0 ; j < m_MatrixWidth - i; j ++)
        {
            //CChecked *pChecked = m_CheckedMatrix[CoordinateToIdx(m_MatrixWidth - j - 1 , j )];
            CalALineDestoryBallCnt(m_MatrixWidth - i - j - 1 , j, curBallType, curDestroyPoint, destroyPoint);
        }

        if (curDestroyPoint.count() >= m_LeastDestoyCnt)
        {
            destroyPoint.append(curDestroyPoint);
        }
    }

    // 西南向遍历下半矩阵
    for (int i = 1; i < m_MatrixWidth; i++)
    {
        int curBallType = eColorTypeNone;
        QList <QPoint> curDestroyPoint;
        curDestroyPoint.clear();
        for (int j = 0 ; j < m_MatrixWidth - i; j ++)
        {
            //CChecked *pChecked = m_CheckedMatrix[CoordinateToIdx(m_MatrixWidth - j - 1, j + i )];
            CalALineDestoryBallCnt(m_MatrixWidth - j - 1, j + i , curBallType, curDestroyPoint, destroyPoint);
        }

        if (curDestroyPoint.count() >= m_LeastDestoyCnt)
        {
            destroyPoint.append(curDestroyPoint);
        }
    }

    return destroyPoint;
}

void CControl::CalALineDestoryBallCnt(int x, int y, int &curBallType,
                                      QList <QPoint> &curDestroyPoint,
                                      QList <QPoint> &totalDestroyBall)
{
    CBall *pBall = NULL;
    CChecked *pChecked = m_CheckedMatrix[CoordinateToIdx(x, y)];
    if (pChecked->hasBall() == false)
    {// 如果这个点 没有小球 则清空
        if (curDestroyPoint.count() >= m_LeastDestoyCnt)
        {
            // 判断之前的数量够不够消除的数量
            // 如果之前的计数已经够消除了 则记录下消除的位置
            totalDestroyBall.append(curDestroyPoint);
            //qDebug() << curDestroyPoint;
        }

        curDestroyPoint.clear();
        curBallType = eColorTypeNone;
    }
    else
    {
        pBall = pChecked->GetBall();
        //destroyPoint.append(QPoint(i, j));
        if (curBallType == eColorTypeNone)
        {
            // 如果这个是新的小球 则初始化当前小球类型和计数
            // 将当前位置 添加到 代销处的位置上
            curBallType = pBall->GetBallType();
            curDestroyPoint.clear();
        }
        else
        {
            if (curBallType != pBall->GetBallType())
            {// 如果和上一个颜色不同
                if (curDestroyPoint.count() >= m_LeastDestoyCnt)
                {
                    // 判断之前的数量够不够消除的数量
                    // 如果之前的计数已经够消除了 则记录下消除的位置
                    totalDestroyBall.append(curDestroyPoint);
                    //qDebug() << curDestroyPoint;
                }

                curBallType = pBall->GetBallType();
                curDestroyPoint.clear();
            }
        }

        curDestroyPoint.append(QPoint(x, y));
    }
}

// 归还空间
void CControl::RestoreSpace(QList<QPoint> pointlist)
{
    CBall *pBall = NULL;

    // 删除小球
    for (int i = 0; i < pointlist.count(); i++)
    {
        QPoint point = pointlist.at(i);
        CChecked *pChecker = m_CheckedMatrix[CoordinateToIdx(point)];

        if (pChecker->hasBall() == true)
        {
            //int idx = m_BallList.indexOf(point);
            pBall = pChecker->GetBall();
            m_BallList.removeOne(pBall);
            pChecker->delBall();

            delete pBall;
        }
    }
}

// 输出矩阵
void CControl::OutputMatrix()
{
    QString outputStr;
    for (int j = 0; j < m_MatrixHeight; j++)
    {
        outputStr += "\r\n";
        for (int i = 0; i < m_MatrixWidth; i ++)
        {
            int state = -1;
            CChecked *pChecked = m_CheckedMatrix[CoordinateToIdx(i, j)];
            if (pChecked->hasBall() == true)
            {
                CBall *pBall = pChecked->GetBall();
                state = pBall->GetBallType();
            }
            outputStr += tr("%1").arg(state, 3, 10) + " ";
        }
    }

    qDebug() << outputStr;


    // 东南向遍历上半矩阵
    outputStr.clear();
    for (int i = 0 ; i < m_MatrixWidth; i++)
    {
        for (int j =0; j < m_MatrixWidth - i; j ++)
        {
            int state = -1;
            CChecked *pChecked = m_CheckedMatrix[CoordinateToIdx(i + j, j)];
            if (pChecked->hasBall() == true)
            {
                CBall *pBall = pChecked->GetBall();
                state = pBall->GetBallType();
            }
            outputStr += tr("%1").arg(state, 3, 10) + " ";
        }
        outputStr += "\r\n";
    }
    //qDebug() << outputStr;

    // 东南向遍历下半矩阵
    outputStr.clear();
    for (int i = 0; i < m_MatrixWidth; i ++)
    {
        for (int j = i ; j < m_MatrixWidth - 1; j ++)
        {
            int state = -1;
            CChecked *pChecked = m_CheckedMatrix[CoordinateToIdx(j - i, j + 1)];
            if (pChecked->hasBall() == true)
            {
                CBall *pBall = pChecked->GetBall();
                state = pBall->GetBallType();
            }
            outputStr += tr("%1").arg(state, 3, 10) + " ";
        }
        outputStr += "\r\n";
    }
    //qDebug() << outputStr;

    // 西南向遍历上半矩阵
    outputStr.clear();
    for (int i = 0 ; i < m_MatrixWidth; i ++)
    {
        for (int j = 0 ; j < m_MatrixWidth - i; j ++)
        {
            int state = -1;
            CChecked *pChecked = m_CheckedMatrix[CoordinateToIdx(m_MatrixWidth - j - 1 , j )];
            if (pChecked->hasBall() == true)
            {
                CBall *pBall = pChecked->GetBall();
                state = pBall->GetBallType();
            }
            outputStr += tr("%1").arg(state, 3, 10) + " ";
        }
        outputStr += "\r\n";
    }
    qDebug() << outputStr;

    // 西南向遍历下半矩阵
    outputStr.clear();
    for (int i = 1; i < m_MatrixWidth; i++)
    {
        for (int j = 0 ; j < m_MatrixWidth - i; j ++)
        {
            int state = -1;
            CChecked *pChecked = m_CheckedMatrix[CoordinateToIdx(m_MatrixWidth - j - 1, j + i )];
            if (pChecked->hasBall() == true)
            {
                CBall *pBall = pChecked->GetBall();
                state = pBall->GetBallType();
            }
            outputStr += tr("%1").arg(state, 3, 10) + " ";
        }
        outputStr += "\r\n";
    }
    //qDebug() << outputStr;

    //exit(0);
}


///
/// \brief CControl::CoordinateToIdx
/// 坐标转换成 索引号
///
/// \param point
/// 坐标
///
/// \return
/// 索引号
///
int CControl::CoordinateToIdx(QPoint point)
{
    return CoordinateToIdx(point.x(), point.y());
}


///
/// \brief CControl::CoordinateToIdx
/// 坐标 准换成 索引号
///
/// \param x
/// 坐标
///
/// \param y
/// 坐标
///
/// \return
/// 索引号
///
int CControl::CoordinateToIdx(int x, int y)
{
    int idx = 0;

    idx = x + y * m_MatrixWidth;

    return idx;
}


void CControl::GetSize(int &widget, int &height)
{
    widget = m_MatrixWidth;

    height = m_MatrixHeight;
}

// 获取小球的指针
bool CControl::GetBall(CBall* &pBall, int x, int y)
{
    CChecked *checked = m_CheckedMatrix[CoordinateToIdx(x, y)];

    if (checked->hasBall() == false)
    {
        return false;
    }
    else
    {
        pBall = checked->GetBall();
        return true;
    }
}


void CControl::SelectChecked(int x, int y)
{
    if (x < 0 || x >= m_MatrixWidth ||
            y < 0 || y > m_MatrixHeight)
    {
        return ;
    }

    QPoint prePoint(m_CheckedBallCoordinate);
    QPoint curPoint(x, y);

    m_CheckedBallCoordinate = curPoint;

    CChecked *preChecked = NULL;
    CChecked *curChecked = m_CheckedMatrix[CoordinateToIdx(curPoint)];
    if (prePoint.x() < 0 || prePoint.y() < 0 ||
            prePoint.x() >= m_MatrixWidth ||
            prePoint.y() >= m_MatrixHeight )
    {
        preChecked = NULL;
    }
    else
    {
        preChecked = m_CheckedMatrix[CoordinateToIdx(prePoint)];
    }

    // 如果之前没有选中过点 则选中点 然后退出
    if (preChecked == NULL)
    {
        if (curChecked->hasBall())
        {
            CBall *pBall;
            pBall = curChecked->GetBall();
            pBall->setCheckState(true);
        }

        return ;
    }

    // 如果是重复选择点
    if (prePoint == curPoint && preChecked->hasBall() == true)
    {
        CBall *pBall;
        pBall = preChecked->GetBall();

        if (pBall->getCheckState() == true)
        {
            // 如果该点之前被选中过 则标记为未选中
            pBall->setCheckState(false);

            // 标记没有选中过点
            m_CheckedBallCoordinate = QPoint(-1, -1);
        }
        else
        {
            // 如果该点没有被选中过 则标记选中
            pBall->setCheckState(true);
        }

        return;
    }

    // 如果这个点有小球
    if (preChecked->hasBall() == true)
    {
        CBall *pBall;
        pBall = preChecked->GetBall();
        pBall->setCheckState(false);

        // 如果之前选中过小球
        if (curChecked->hasBall() == true)
        {// 如果当前选中的点也有一个小球
            pBall = curChecked->GetBall();
            pBall->setCheckState(true);
        }
        else
        {// 查看是否可以移动到这里
            if (MoveBall(prePoint, curPoint) == true)
            {
                emit BallHasMoved(m_MovePath);

                // 标记为没有点被选中
                m_CheckedBallCoordinate = QPoint(-1, -1);
            }
        }

    }
    else
    {
        // 选中这个点
        if (curChecked->hasBall() == true)
        {
            CBall *pBall;
            pBall = curChecked->GetBall();
            pBall->setCheckState(true);
        }

    }

    //OutputMatrix();
}


QList <QPoint> CControl::GetSpaceChecked()
{
    QList <QPoint> space;
    // 归还剩余空间
    space.clear();
    for (int i = 0; i < m_MatrixWidth; i++)
    {
        for (int j = 0; j < m_MatrixHeight; j++)
        {
            if (m_CheckedMatrix[CoordinateToIdx(i, j)]->hasBall() == false)
            {
                space.append(QPoint(i, j));
            }
        }
    }

    return space;
}
